<?php

class ComponentController extends GenesisController
{
    /**
     * Inits the controller and appends requried js files to headscript.
     */
    public function init() {
        parent::init();
        $this->view->headScript()->appendFile('/js/jquery/ajaxupload.js');

    }

    /**
     * Inserts a component usage row.
     *
     * Requires:_REQUEST['component_id']        , _REQUEST['component_enabled']
     *          _REQUEST['component_top']       , _REQUEST['component_left']
     *          _REQUEST['component_height']    , _REQUEST['component_width']
     *          _REQUEST['component_theme_name'], _REQUEST['component_label']
     * Optional:_REQUEST['params'] array of params
     */
    public function insertComponentUsageRowAction() {
    	
        $component_id=$this->_request->getParam('component_id');
        $component_enabled=$this->_request->getParam('component_enabled');
        $component_top=$this->_request->getParam('component_top');
        $component_left=$this->_request->getParam('component_left');
        $component_height=$this->_request->getParam('component_height');
        $component_width=$this->_request->getParam('component_width');
        $component_theme=$this->_request->getParam('component_theme_name');
        $component_label=$this->_request->getParam('component_label');
        $reqParams=$this->_request->getParams();
        $params=array();
        foreach  ($reqParams as $key=>$value) {
            if (preg_match('/^option_(.*)$/',$key,$matches) == 1)
                $params[$matches[1]]=$value;
        }
        
        $componentUsage = new Default_Model_ComponentUsage();
        $componentUsage->setComponentId($component_id);
        $componentUsage->setEnabled($component_enabled);
        $componentUsage->setTop($component_top);
        $componentUsage->setLeft($component_left);
        $componentUsage->setHeight($component_height);
        $componentUsage->setWidth($component_width);
        $componentUsage->setThemeName($component_theme);
        $componentUsage->setLabel($component_label);
        $componentUsage->setParams(json_encode($params));

        $componentUsage->save();

                // to fetch the saved timestamp
        $componentUsage->find($componentUsage->getId());
        $result=$componentUsage->toArray();
        $component = new Default_Model_Components();
        $component->find($component_id);
        $result['component_name']=$component->getName();
        $this->view->message=json_encode($result);

    }


    /**
     * List components action - loads required css and js for view.
     */
    public function listComponentsAction()
    {
        $this->view->headLink()->appendStylesheet('/js/jqGrid/themes/ui.jqgrid.css');
        $this->view->headScript()->appendFile('/js/jqGrid/js/i18n/grid.locale-en.js');
        $this->view->headScript()->appendFile('/js/jqGrid/js/jquery.jqGrid.js');
        

    	$this->view->headLink()->appendStylesheet('/css/list-components.css');

    }


    /**
     * Handler for add, del, and edit action of jqGrid componentsUsageTable.
     *
     * Requires: _REQUEST['component_name'] , _REQUEST['enabled']
     *           _REQUEST['height']         , _REQUEST['width']
     *           _REQUEST['id']             , _REQUEST['left']
     *           _REQUEST['top']            , _REQUEST['theme_name']
     *           _REQUEST['label']          , _REQUEST['params'],
     *           _REQUEST['oper'] - operation to perform
     */
    public function setComponentsUsageListAction() {

        $componentName=$this->_request->getParam('component_name');
        $enabled=$this->_request->getParam('enabled');
        $height=$this->_request->getParam('height');
        $id=$this->_request->getParam('id');
        $left=$this->_request->getParam('left');
        $top=$this->_request->getParam('top');
        $width=$this->_request->getParam('width');
        $themeName=$this->_request->getParam('theme_name');
        $label=$this->_request->getParam('label');
        $params=$this->_request->getParam('params');

        $oper = $this->_request->getParam('oper');

        if ($componentName != '') {
                $component = new Default_Model_Components();
                $component->findOneByName($componentName);
                $componentId=$component->getId();
        }
        $componentUsage = new Default_Model_ComponentUsage();

        if (in_array($oper,array('del','edit')))
            $componentUsage->find($id);
        if ($oper == 'del') {
            $componentUsage->deleteRowByPrimaryKey();
        } else {
            $componentUsage->setComponentId($componentId);
            $componentUsage->setEnabled($enabled);
            $componentUsage->setHeight($height);
            $componentUsage->setWidth($width);
            $componentUsage->setTop($top);
            $componentUsage->setLeft($left);
            $componentUsage->setThemeName($themeName);
            $componentUsage->setLabel($label);
            $componentUsage->setParams($params);
            $componentUsage->save();
        }
        
    }

    /**
     * Gets component usage list from db according to page, rows, sidx and sord.
     *
     * Requires: _REQUEST['page'] , _REQUEST['rows']
     *           _REQUEST['sidx'] , _REQUEST['sord']
     *
     * Returns: Array where 'page'    => Page number
     *                      'total'   => Total number of pages
     *                      'records' => Total number of rows
     *                      'rows'    => Component usage rows as an Array
     *          Returned as json message in $view->jsonMessage
     */
    public function getComponentsUsageListAction() {

        $page = $this->_request->getParam('page'); // get the requested page
        $limit = $this->_request->getParam('rows'); // get how many rows we want to have into the grid
        $sidx = $this->_request->getParam('sidx'); // get index row - i.e. user click to sort
        $sord = $this->_request->getParam('sord'); // get the direction if(!$sidx) $sidx =1;


        $componentUsage 						= new Default_Model_ComponentUsage();
        $component = new Default_Model_Components();
        $records = $componentUsage->countAllRows();
        $total=ceil(($records)/$limit);
        if ($page > $total)
                $page=$total;
        $list =  $componentUsage->fetchListToArray(null, $sidx.' '.$sord, $limit, ($page == 0 ? 0 : ($page-1)*$limit));
        $rows=array();
        foreach ($list as $row) {
            $component->find($row['component_id']);
            $rows[]=array(
                'id'=>$row['id'],
                'cell'=>array($row['id'],
                              $component->getName(),
                              $row['top'],
                              $row['left'],
                              $row['height'],
                              $row['width'],
                              $row['theme_name'],
                              $row['label'],
                              $row['enabled'],
                              $row['params'],
                              $row['timestamp'])
                );
        }
        $ret = array(
            'page'=>$page,
            'total'=>$total,
            'records'=>$records,
            'rows'=>$rows);
        $this->view->jsonMessage=json_encode($ret);
        
    }

    /**
     * Gets component list from db according to page, rows, sidx and sord.
     *
     * Requires: _REQUEST['page'] , _REQUEST['rows']
     *           _REQUEST['sidx'] , _REQUEST['sord']
     *
     * Returns: Array where 'page'    => Page number
     *                      'total'   => Total number of pages
     *                      'records' => Total number of rows
     *                      'rows'    => Component usage rows as an Array
     *          Returned as json message in $view->jsonMessage
     */
    public function getComponentsListAction() {

        $page = $this->_request->getParam('page'); // get the requested page
        $limit = $this->_request->getParam('rows'); // get how many rows we want to have into the grid
        $sidx = $this->_request->getParam('sidx'); // get index row - i.e. user click to sort
        $sord = $this->_request->getParam('sord'); // get the direction if(!$sidx) $sidx =1;


        $componentUsage 						= new Default_Model_Components();
        $records = $componentUsage->countAllRows();
        $list = $componentUsage->fetchListToArray(null, $sidx.' '.$sord, $limit, ($page-1)*$limit);
        $total=ceil(($records)/$limit);
        if ($page > $total)
                $page=$total;
        $rows=array();
        foreach ($list as $row) {
            $rows[]=array(
                'id'=>$row['id'],
                'cell'=>array($row['id'],
                              $row['name'],
                              $row['version'],
                              $row['location'],
                              $row['min_height'],
                              $row['min_width'],
                              $row['timestamp'])
                );
        }
        $ret = array(
            'page'=>$page,
            'total'=>$total,
            'records'=>$records,
            'rows'=>$rows);
        $this->view->jsonMessage=json_encode($ret);

    }


    /**
     * List components usages action - loads required css and js for view, and
     * loads required vars for displaying the view.
     *
     * Returns:     $this->view->components - Array of components names
     *              $this->view->themes     - Array of theme names
     *              $this->view->jqGridTheme- Current selected theme name
     */
    public function listComponentsUsageAction()
    {
        // Currently there is a problem loading the plugin, edit gid.jqueryui.js to make sure that the plugin is loaded and if it is, to load it
        //$this->view->headScript()->appendFile('/js/jquery/ui.multiselect/js/ui.multiselect.js');
        //$this->view->headLink()->appendStylesheet('/js/jquery/ui.multiselect/css/ui.multiselect.css');

        $this->view->headLink()->appendStylesheet('/js/jqGrid/themes/ui.jqgrid.css');
        $this->view->headScript()->appendFile('/js/jqGrid/js/i18n/grid.locale-en.js');
        $this->view->headScript()->appendFile('/js/jqGrid/js/jquery.jqGrid.js');

        $this->view->headScript()->appendFile('/js/jquery/jquery.form.js');
        $components = new Default_Model_Components();
        $rows=$components->getOrderedComponentsNamesArray();
        $this->view->components=$rows;

        $themesDir=$this->_config->themes->path;

        $jqGridTheme=$this->_config->jqgrid->theme;

        $themes=array();
        $handle = opendir($themesDir);

        if ($handle) {

            while (($file = readdir($handle)) !== false) {
                if (substr($file,0,1) == '.') continue;
                if (is_dir($themesDir.DIRECTORY_SEPARATOR.$file) && is_file($themesDir.DIRECTORY_SEPARATOR.$file.DIRECTORY_SEPARATOR.$file.'.php'))
                    $themes[]=$file;
            }
            closedir($handle);
        }

        $this->view->themes=$themes;
        $this->view->jqGridTheme=$jqGridTheme;

    }

    /**
     * Installs a new component.
     *
     * @param string $path
     * @param string $componentDir
     * @return Array
     */
    private function _installComponentDir($path,$componentDir) {
        $errorArray=array();
        $componentLocation=realpath($path).DIRECTORY_SEPARATOR.$componentDir;

        $iniComponentFile = $componentLocation.DIRECTORY_SEPARATOR.'ini'.DIRECTORY_SEPARATOR.$componentDir.'.ini';

        $componentIni = new Zend_Config_Ini($iniComponentFile,'default');
        
        $sqlComponentFile = $componentLocation.DIRECTORY_SEPARATOR.'sql'.DIRECTORY_SEPARATOR.'install.sql';
        
        $phpComponentFile = $componentLocation.DIRECTORY_SEPARATOR.'php'.DIRECTORY_SEPARATOR.$componentIni->php->mainfile;

        $className=$componentIni->php->classname;

        $db = Zend_Db_Table::getDefaultAdapter();

        if (is_file($sqlComponentFile)) {
            foreach (explode(';',file_get_contents($sqlComponentFile)) as $sql) {
                if (trim($sql) == '')
                    continue;

                $db->query($sql);
            }
        }
        $jqGridTheme = $this->_config->jqgrid->theme;
        $imagesUri=$this->_config->images->uri;
        try {
                require_once($phpComponentFile);
                $testClass = new $className($jqGridTheme, $path,$componentDir,$imagesUri);
        } catch (Exception $e) {
                $errorArray=array('success'=>0,'message'=>'could not load Component\'s class: '.$e->getMessage());
            return $errorArray;
        }

        $component = new Default_Model_Components();

        $component->setLocation($componentDir);
        $component->setName($componentIni->name);
        $component->setVersion($componentIni->version);
        $component->setMinHeight($componentIni->style->minheight);
        $component->setMinWidth($componentIni->style->minwidth);

        $component->save();
        $id = $component->getId();

        $this->_initComponentMenu($componentIni, $id);
        
        $errorArray=array('success'=>1,'message'=>"component {$componentIni->name} installed successfull");
        return $errorArray;


    }

    /**
     * Adds required menu entries for newly installed component.
     *
     * @param Zend_Config_Ini $componentIni
     * @param int $id
     */
    private function _initComponentMenu($componentIni, $id){
            $navpath = APPLICATION_PATH.DIRECTORY_SEPARATOR.'xml'.DIRECTORY_SEPARATOR.'navigation.xml';
            $nav = new Zend_Config_Xml($navpath, 'nav',array('skipExtends'        => true,'allowModifications' => true));
            $name = $componentIni->name;

            $escapedName = preg_replace('/(\s+)/', '_', $name);


            if (!isset ($nav->admin->pages->components->pages))
            {
                @$nav->admin->pages->components->pages = array();
            }
            $nav->admin->pages->components->pages->$escapedName = array();
            $nav->admin->pages->components->pages->$escapedName->label = $name;
            $nav->admin->pages->components->pages->$escapedName->uri   = "/";
            $nav->admin->pages->components->pages->$escapedName->pages = array();

            if(isset($componentIni->page->config->enabled)
                && $componentIni->page->config->enabled == true) {
                $nav->admin->pages->components->pages->$escapedName->pages->config = array();
                $nav->admin->pages->components->pages->$escapedName->pages->config->label = 'Config';
                $nav->admin->pages->components->pages->$escapedName->pages->config->uri   = '/component-plugin/get-component-config-page/id/'.$id;
            }
            
            $nav->admin->pages->components->pages->$escapedName->pages->demo = array();
            $nav->admin->pages->components->pages->$escapedName->pages->demo->label   = 'Demo';
            $nav->admin->pages->components->pages->$escapedName->pages->demo->uri     = '/component-plugin/get-component-demo/id/'.$id;

            $writer = new Zend_Config_Writer_Xml(array('config'   => $nav,
                                                       'filename' => $navpath));
            $writer->write();           
    }

    /**
     *
     * Checks if a component is installed by the component's location
     *
     * @param string $location
     * @return bool 
     */
    private function _isComponentInstalledByLocation($location) {
        $components = new Default_Model_Components();
        $components->findOneByLocation($location);
        return is_numeric($components->getId());
    }

    /**
     * Install all available components that reside in components directory.
     */

    public function installAllComponentsInComponentsDirAction() {
        $componentsDir=$this->_config->components->path;
        $components=array();
        $messages=array();
        if ($handle = opendir($componentsDir)) {

            while (($file = readdir($handle)) !== false) {
                if (substr($file,0,1) == '.' or $file=='skeleton' or $file == 'temp')  continue;
                if (is_dir($componentsDir.DIRECTORY_SEPARATOR.$file))
                    $components[]=$file;
            }
            closedir($handle);
        }
        foreach ($components as $componentFile) {
            
            if ($this->_isComponentInstalledByLocation($componentFile)) {
                    $messages[]=array('success'=>0,'message'=>"$componentFile: component already installed");
                    continue;
            }
            $messages[]=$this->_installComponentDir($componentsDir,$componentFile);
        }
        $this->view->messages=$messages;
       
    }

    /**
     * Uploads a component archive and unpacks it.
     */

    public function uploadAction() {
   	
    	$this->_helper->layout()->disableLayout();   	
   		$file=$_FILES['componentfile'];
    	$message=null;
    	if ($file['error']>0) {
    		$message=array('sucess'=>0,'message'=>'error uploading file');
    		$this->_helper->FlashMessenger($message);
    		
    	}
    	else {
    		$unpackers = new Default_Model_Unpackers();
    		$ret=$unpackers->getUnpackerInformation($file['type']);
    		if (is_null($ret)) {
    			$message=array('success'=>0,'message'=>"unknown mimetype {$file['type']}, please notify admin.");
    			$this->_helper->FlashMessenger($message);
    		}
    		else {
    			$archive = $this->_registry->files_config->$ret['file']->location;
    			if ($archive == '' or !is_file($archive)) {
    				$message=array('success'=>0,'message'=>"could not find archive {$ret['file']}, please notify system admin.");
    				$this->_helper->FlashMessenger($message);
    			}
    				else {
    				$tempDir=$this->_config->components->tmp_path;
    				$componentsDir=$this->_config->components->path;
    				if (!is_dir($tempDir))   {
    					if (!mkdir($tempDir))  {
    						$message=array('success'=>0,'message'=>"could not create temp directory '$tempDir'.");
    						$this->_helper->FlashMessenger($message);
    					}
    				}
    					else {
    						
    						if (!is_writeable($tempDir)) {
    							$message=array('success'=>0,'message'=>"'$tempDir' is not writeable.");
    							$this->_helper->FlashMessenger($message);
    						} else {
    						
    						$unpackParams=str_replace('<#FILE#>','"'.$file['tmp_name'].'"',$ret['params']);
    						$unpackParams=str_replace('<#DIR#>','"'.$tempDir.'"',$unpackParams);
    						$command="$archive $unpackParams";
    						`$command`;
    						if (!$dh = opendir($tempDir)) {
    							$message=array('success'=>0,'message'=>"could not open $tempDir for reading!");
    							$this->_helper->FlashMessenger($message);
    						}

                                                do {
    							$obj=readdir($dh);
    						}
    						while (substr($obj,0,1) == '.');
    						
    						if (readdir($dh) !== false) {
    							`rm -rf {$tempDir}/*`;
    							$message=array('success'=>0,'message'=>'root directory archive needs to contain only the module directory!');
    							$this->_helper->FlashMessenger($message);
    						} else {
    							
    							$tempComponentDir="$tempDir/$obj";
    							if (!is_dir($tempComponentDir.'/ini')) {
    								
    								$message=array('success'=>0,'message'=>'could not find ini directory in component directory.');
    								$this->_helper->FlashMessenger($message);
    								`rm -rf $tempComponentDir`;
    							
    							} else {
                                                                $message=$this->_installComponentDir($tempDir,$obj);

                                                                if ($message['success'] == 1) {

                                                                    `mv $tempComponentDir $componentsDir`;
                                                                    $message=array('success'=>1,'message'=>"finished installing {$obj} version {$componentIni->version}.");
                                                                    
                                                                }
                                                                
    								$this->_helper->FlashMessenger($message);

    							}
    								
    							
    						}
    						}
    						
    					}
    				}
    				
    		
    		}
    	}
    	
    	$this->view->message=json_encode($message);
    
    }
    
    public function indexAction()
    {
        // action body
    }

    /**
     * Removes a component.
     *
     * Required:    _REQUEST['id'], _REQUEST['name']
     *
     * Returns:     $this->view->result - Array containing: success => 1 if succesful, 0 otherwise.
     *                                                      message => error message if success = 0
     */
    public function removeComponentAction() {
        $id=$this->_request->GetParam('id');
        $name=$this->_request->GetParam('name');

        $componentsDir=$this->_config->components->path;

        
        if (!is_numeric($id)) {
           $this->view->result=json_encode(array('success'=>0,'message'=>'id is not numeric'));
           return;
        }
        
        $component = new Default_Model_Components();
        $component->find($id);
        $location = $component->getLocation();
        $uninstallSqlFile=$componentsDir.DIRECTORY_SEPARATOR.$location.DIRECTORY_SEPARATOR.'sql'.DIRECTORY_SEPARATOR.'uninstall.sql';
        $dbName=$this->_config->resources->db->params->dbname;
        $username=$this->_config->resources->db->params->username;
        $password=$this->_config->resources->db->params->password;
        if ($password != '')
                $password == "-p".$password;

        if (is_file($uninstallSqlFile)) {

            $db = Zend_Db_Table::getDefaultAdapter();
            foreach (trim(';',file_get_content($uninstallSqlFile)) as $sql) {
                if (trim($sql) == '')
                    continue;

                $db->query($sql);
            }

        }

        $componentUsage = new Default_Model_ComponentUsage();
        $componentUsage->deleteRowsByComponentId($id);
        $component->deleteRowByPrimaryKey();

        $navpath = APPLICATION_PATH.DIRECTORY_SEPARATOR.'xml'.DIRECTORY_SEPARATOR.'navigation.xml';
        $nav = new Zend_Config_Xml($navpath, 'nav',array('skipExtends'        => true,'allowModifications' => true));

        if (isset($nav->components->pages->$name))
            unset($nav->components->pages->$name);
        if (isset($nav->components->pages) && $nav->components->pages->count() == 0)
        {
           unset($nav->components->pages);
        }

        $writer = new Zend_Config_Writer_Xml(array('config'   => $nav,
                                                       'filename' => $navpath));
        $writer->write();

        $this->view->result=json_encode(array('success'=>1,'message'=>'done'));

    }

}









